const fs = require("fs")
const path = require("path")
const fse = require('fs-extra');
const os = require('os');
const execSync = require('child_process').execSync;
module.exports = handleReactTemplate

function handleReactTemplate(basePath, viewAnswer, isAll, pluginType) {
  handleAppjs(basePath, viewAnswer)
  handleComponentsIndexjs(basePath, viewAnswer)
  handleComponentDevelopmentIndexjs(basePath, viewAnswer)
  handleComponentDevelopmentMockDatajs(basePath, viewAnswer)
  handleUtilHandlePlatformAdapterjs(basePath,viewAnswer)
  generateNewFiles(basePath, viewAnswer)
  deleteExtraFiles(basePath, viewAnswer)
  basePath = moveFiles(basePath, isAll, pluginType)
  return basePath
}

function moveFiles(basePath, isAll, pluginType) {
  let pathPrefix
  //通过本项目启动
  if (process.env["sdataPlugins"] === "true") {
    pathPrefix = path.resolve(__dirname, `../packages`)
  } else {
    pathPrefix = process.cwd()
  }
  if (isAll) {
    mkdirSync(path.resolve(pathPrefix, `${pluginType}/${basePath}`))
    fse.copySync(path.resolve(__dirname, `./${basePath}`), path.resolve(pathPrefix, `${pluginType}/${basePath}`))
    mkdirSync(path.resolve(pathPrefix, `${pluginType}/src/utils/handlePlatform`))
    fse.copySync(path.resolve(__dirname, `./${basePath}/src/utils/handlePlatform/adapter.js`), path.resolve(pathPrefix, `${pluginType}/src/utils/handlePlatform/adapter.js`))
    mkdirSync(path.resolve(pathPrefix, `${pluginType}/src/components/development`))
    fse.copySync(path.resolve(__dirname, `./${basePath}/src/components/development/mockData.js`), path.resolve(pathPrefix, `${pluginType}/src/components/development/mockData.js`))
    fse.removeSync(path.resolve(__dirname, `./${basePath}`))
    basePath = path.resolve(pathPrefix, `${pluginType}`)
    return basePath
  } else {
    mkdirSync(path.resolve(pathPrefix, basePath))
    fse.copySync(path.resolve(__dirname, `./${basePath}`), path.resolve(pathPrefix, basePath))
    fse.removeSync(path.resolve(__dirname, `./${basePath}`))
    basePath = path.resolve(pathPrefix, basePath)
    let batchFlag = process.argv.slice(2)[0] == "--batch"
    !batchFlag && openFiles(basePath)
  }
}


function openFiles(basePath) {
  let startCommond = os.type() === "Darwin" ? "open" : "start"
  try {
    execSync(`${startCommond} ${basePath}`)
    execSync(`${startCommond} ${basePath}/src/utils/handlePlatform/adapter.js`)
    execSync(`${startCommond} ${basePath}/src/components/development/mockData.js`)
  } catch (e) {
    console.log("自动打开文件失败，请手动打开，目录名：src/utils/handlePlatform/adapter.js")
    console.log("自动打开文件失败，请手动打开，目录名：src/components/development/mockData.js")
  }
}

// handleComponentDevelopmentMockDatajs("", [
//   {viewType: "main", process: false},
//   {viewType: "designConfiguration", process: false},
//   {viewType: "data", process: true}
// ])

function handleUtilHandlePlatformAdapterjs(basePath, viewAnswer) {
  const needProcess = viewAnswer.some((item) => {
    return item.process == true
  })
  const templateContent = `export default function adapter(props) {
  const onlineDevelopmentMode = process.env.VUE_APP_ONLINE_DEVELOPMENT_MODE === "true" || process.env.REACT_APP_ONLINE_DEVELOPMENT_MODE === "true"
  if (process.env.NODE_ENV === "production" || (onlineDevelopmentMode && !window.online_development_islocal)) {
    /**
     *@example
     * props.type = (props.type === "designConfiguration" ? "designConfiguration" : "main")
     *   props.changeConfiguration && (props.changeCustomConfig = props.changeConfiguration)
     *   if (props.type === "designConfiguration") {
     *     props.customConfig = JSON.parse(props.configuration)
     *   } else {
     *     props.customConfig = props.configuration
     *   }
     *
     */
     ${needProcess
    ? "/**\n     * 封装smardaten触发事件的方法\n     * @param {String} eventName 事件名\n     * @param {Object} payload 事件传参\n     * @example\n     * triggerEvent(\"click\",{value:\"123\"})\n     *\n     */\n    /*props.triggerEvent = function (eventName, payload = {}) {\n     props.componentId && window.eventCenter?.triggerEvent(\n     props.componentId,\n     eventName,\n     //payload需为一个object\n     payload\n     )\n     }*/"
    : ""}
    // return props
  }
  return props
}
`
  fs.writeFileSync(path.resolve(__dirname, `./${basePath}/src/utils/handlePlatform/adapter.js`), templateContent)
}

function handleComponentDevelopmentMockDatajs(basePath, viewAnswer) {
  const hasDesignConfiguration = viewAnswer.some((item) => {
    return item.viewType == "designConfiguration"
  })
  const templateContent = `import getPluginType from "../../utils/handlePlatform/getPluginType.js"
  
const pluginType = getPluginType()
${hasDesignConfiguration
    ? "const configJson = require('../../../pluginTemp/config.json');\nconst configJsonId = configJson.id\nlet customConfig = JSON.parse(localStorage.getItem(`${pluginType}-secondary-${configJsonId}`))?.customConfig || {}\nexport let mockCustomConfig = customConfig\nexport const mockChangeCustomConfig = (customConfig) => {\n  const mockData = JSON.parse(localStorage.getItem(`${pluginType}-secondary-${configJsonId}`)) || {}\n  mockData.customConfig = JSON.parse(customConfig)\n  localStorage.setItem(`${pluginType}-secondary-${configJsonId}`, JSON.stringify(mockData))\n}"
    : ""}
export default {

}
  `
  // console.log(templateContent);
  fs.writeFileSync(path.resolve(__dirname, `./${basePath}/src/components/development/mockData.js`), templateContent)
}

function handleComponentDevelopmentIndexjs(basePath, viewAnswer) {
  const hasDesignConfiguration = viewAnswer.some((item) => {
    return item.viewType == "designConfiguration"
  })
  let importStatement = viewAnswer.map((item) => {
    let componentName = `${item.viewType.slice(0, 1).toUpperCase()}${item.viewType.slice(1)}`
    return `${componentName}`
  }).join(",\n  ")
  let templateContent = `import "./development.less"
import {
  ${importStatement}
} from "../index.js"${hasDesignConfiguration
    ? "\nimport mockData, {\n  mockCustomConfig,\n  mockChangeCustomConfig\n} from \"./mockData.js\""
    : "\nimport mockData from \"./mockData.js\""}
import Utils from "../../utils"

const { useEffect, useRef, useState } = window.React
const { Carousel${hasDesignConfiguration ? ", Button" : ""} } = window.antd
const renderMap = [
  ${viewAnswer.filter((item) => item.viewType != "designConfiguration").map((item) => {
    let componentName = `${item.viewType.slice(0, 1).toUpperCase()}${item.viewType.slice(1)}`
    return `{ type: "${componentName}", component: ${componentName} }`
  }).join(",\n  ")}
]
const Development = () => {
  const carousel = useRef()
  let [mainKey, setMainKey] = useState(Utils.generateUUID)
  ${hasDesignConfiguration
    ? "const side = useRef()\n  const toggle = useRef()\n  const [customConfig, setCustomConfig] = useState(mockCustomConfig)\n  const toggleShrink = () => {\n    let sideClose = side.current.style.display == \"none\" ? true : false\n    side.current.style.display = sideClose ? \"block\" : \"none\"\n    carousel.current.style.width = sideClose ? \"calc(100% - 300px)\" : \"100%\"\n    toggle.current.style.transform = sideClose ? \"translateX(-50%)\" : \"translateX(-50%) rotateY(180deg)\"\n  }\n  const changeCustomConfig = (customConfig) => {\n    setCustomConfig(JSON.parse(customConfig))\n    setMainKey(Utils.generateUUID())\n    mockChangeCustomConfig(customConfig)\n  }"
    : ""}
  let props = {${hasDesignConfiguration ? "\n    customConfig," : ""}
    ...mockData
  }
  
  return (
    <div id="development">
      <div ref={carousel} style={{position: "relative"}}>${hasDesignConfiguration
    ? "\n        <Button\n          style={{\n            width: \"40px\",\n            zIndex: \"2000\",\n            height: \"40px\",\n            position: \"absolute\",\n            top: \"50%\",\n            right: 0,\n            display: \"flex\",\n            transform: \"translate(50%,-50%)\",\n            borderRadius: \"50%\"\n          }}\n          onClick={toggleShrink}\n        >\n          <svg\n            viewBox=\"0 0 24 24\"\n            ref={toggle}\n            style={{\n              position: \"absolute\",\n              width: \"30px\",\n              height: \"30px\",\n              transform: \"translateX(-50%) rotateY(180deg)\"\n            }}\n          >\n            <path d=\"M8.59,16.58L13.17,12L8.59,7.41L10,6L16,12L10,18L8.59,16.58Z\"></path>\n          </svg>\n        </Button>"
    : ""}
        <Carousel key={mainKey}>
          {
            renderMap.map((item, renderMapIndex) => {
              let Comp = item.component
              return (
                <div key={renderMapIndex} className="carousel-item" type={item.type}>
                  <Comp {...props} />
                </div>)
            })
          }
        </Carousel>
      </div>
      ${hasDesignConfiguration
    ? "<div\n        id=\"configuration\"\n        ref={side}\n        style={{display: \"none\", position: \"absolute\", top: 0, right: 0, zIndex: 2001}}\n      >\n        <DesignConfiguration changeCustomConfig={changeCustomConfig} {...props} />\n      </div>"
    : ""}
    </div>
  )
}

export default Development
`
  // console.log(templateContent);
  fs.writeFileSync(path.resolve(__dirname, `./${basePath}/src/components/development/index.js`), templateContent)
}

function deleteExtraFiles(basePath, viewAnswer) {
  if (!viewAnswer.some((item) => item.viewType === "designConfiguration")) {
    fse.removeSync(path.resolve(__dirname, `./${basePath}/src/components/designConfiguration`))
  }
  if (viewAnswer.some(item => item.viewType == "main" && item.process == false)) {
    fse.removeSync(path.resolve(__dirname, `./${basePath}/src/components/main/eventActionDesinitions.js`))
  }
}

function generateNewFiles(basePath, viewAnswer) {
  const hasDesignConfiguration = viewAnswer.some((item) => {
    return item.viewType == "designConfiguration"
  })
  viewAnswer.forEach((item) => {
    let templateContent = ""
    if (item.viewType != "designConfiguration") {
      let componentName = `${item.viewType.slice(0, 1).toUpperCase()}${item.viewType.slice(1)}`
      templateContent = `${item.process
        ? "import useDelegator from \"../../utils/handlePlatform/UseDelegator.js\";\nimport EventActionDefinitions from \"./eventActionDefinitions.js\"\n\n"
        : ""}const { useEffect, useRef, useState } = window.React
const ${componentName} = (props) => {${hasDesignConfiguration ? "\  const [number, setNumber] = useState(1)" : ""}
  const initComData = () => {\n    ${hasDesignConfiguration ? "customConfig.number && setNumber(customConfig.number)\n" : ""}  }\n
  ${hasDesignConfiguration ? "const customConfig = props?.customConfig" : ""}
  ${item.process
        ? "  const do_EventCenter_message = ({ value }) => {\n    alert(value)\n  }\n  const actionFunDefinitions = {\n    do_EventCenter_message\n  }\n  const handleClick = () => {\n    props.triggerEvent?.(\"click\", { value: \"123\" })\n  }\n  useDelegator(props, actionFunDefinitions, EventActionDefinitions)"
        : ""}
  useEffect(() => {\n    initComData()\n  }, [])
  return (
    <>
      <div>
        {/*以下为样例，正式开发请去除相关代码*/}
        ${hasDesignConfiguration ? "{number}" : ""}${item.process ? "\n         <button onClick={handleClick}>逻辑控制事件触发样例</button>" : ""}
      </div>
    </>
  )
}

export default ${componentName}
`
    } else {
      templateContent = `function DesignConfiguration(props) {
  //此处的customConfig已经封装完毕，可以直接使用
  const {Button, Input} = window.antd
  const {changeCustomConfig, customConfig} = props;
  const {useState} = window.React
  const [id, setId] = useState(customConfig.id)
  const idChange = ({target}) => {
    customConfig.id = target.value
    setId(target.value)
    changeCustomConfig(JSON.stringify(customConfig))
  }
  //此处为最简单的样例
  !customConfig.number && (customConfig.number = 1);
  const handleClick = () => {
    customConfig.number++;
    changeCustomConfig(JSON.stringify(customConfig));
  };
  return (
    <div>
      <div>id:</div>
      <Input onChange={idChange} value={id}></Input>
      <Button onClick={handleClick}>配置项与主渲染区域交互样例</Button>
    </div>
  );
}

export default DesignConfiguration;

`
    }
    mkdirSync(path.resolve(__dirname, `./${basePath}/src/components/${item.viewType}`))
    if (item.process) {
      fse.copySync(path.resolve(__dirname, `./react/src/components/main/eventActionDefinitions.js`), path.resolve(__dirname, `./${basePath}/src/components/${item.viewType}/eventActionDefinitions.js`))
    }
    fs.writeFileSync(path.resolve(__dirname, `./${basePath}/src/components/${item.viewType}/index.js`), templateContent)
    // console.log(templateContent);
  })

}

function mkdirSync(dirname) {
  if (fs.existsSync(dirname)) {
    return true
  } else {
    //如果父级目录已经创建，然后才能创建子级目录
    if (mkdirSync(path.dirname(dirname))) {
      fs.mkdirSync(dirname)
      return true
    }
  }
}

function handleComponentsIndexjs(basePath, viewAnswer) {
  let importStatement = viewAnswer.map((item) => {
    let componentName = `${item.viewType.slice(0, 1).toUpperCase()}${item.viewType.slice(1)}`
    return `import ${componentName} from "./${item.viewType}";`
  }).join("\n")
  let exportStatement = viewAnswer.map((item) => {
    let componentName = `${item.viewType.slice(0, 1).toUpperCase()}${item.viewType.slice(1)}`
    return `${componentName}`
  }).join(",\n  ")
  let componentsIndexjs = `${importStatement}
import Development from "./development";
import OnlineDevelopmentModeDetails from "./development/onlineDevelopmentModeDetails.js";
export {
  Development,
  OnlineDevelopmentModeDetails,
  ${exportStatement}
};

`
  // console.log(componentsIndexjs)
  fs.writeFileSync(path.resolve(__dirname, `./${basePath}/src/components/index.js`), componentsIndexjs)
}

function handleAppjs(basePath, viewAnswer) {
  let importStatement = viewAnswer.map((item) => {
    let componentName = `${item.viewType.slice(0, 1).toUpperCase()}${item.viewType.slice(1)}`
    return `${componentName}`
  }).join(",\n  ")
  let renderMap = viewAnswer.map((item) => {
    let componentName = `${item.viewType.slice(0, 1).toUpperCase()}${item.viewType.slice(1)}`
    return `${item.viewType}: ${componentName}`
  }).join(",\n  ")
  let reactAppjs = `import {
  ${importStatement}
} from "./components"

const renderMap = {
  ${renderMap}
}
const App = (props) => {
  let Comp = () => <></>
  if (renderMap[props.type]) Comp = renderMap[props.type]
  return <Comp {...props} />
}
App.propTypes = {}

export default App
`
  fs.writeFileSync(path.resolve(__dirname, `./${basePath}/src/App.js`), reactAppjs)
  // console.log(reactAppjs)
}